package cn.lhz.util.list;

import cn.lhz.util.annotation.FieldAnnotation;
import cn.lhz.util.annotation.RowKeyAnnotation;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author 李昊哲
 * @version 1.0.0
 */
public class ListToChart {

  /**
   * 获取集合元素中的主键集合 该主键属性必须使用 RowKeyAnnotation 注解修饰
   *
   * @param dataList 数据列表
   * @param clazz    集合泛型
   * @param <T>      泛型
   * @return 主键集合
   */
  public static <T> List<Object> getRowKeyList(List<T> dataList, Class<T> clazz) throws IllegalAccessException {
    List<Object> rowKeyList = new ArrayList<>();
    Field[] fields = clazz.getDeclaredFields();
    for (T data : dataList) {
      for (Field field : fields) {
        // 设置私有属性可以访问权限
        field.setAccessible(true);
        // 获取属性 RowKeyAnnotation 注解
        RowKeyAnnotation rowKeyannotation = field.getAnnotation(RowKeyAnnotation.class);
        if (rowKeyannotation != null) {
          rowKeyList.add(field.get(data));
        }
      }
    }
    return rowKeyList;
  }

  /**
   * 获取集合元素中的非主键元素别名集合 <br />
   * 主键属性必须使用 RowKeyAnnotation 注解修饰 <br />
   * 非主键属性必须使用 FieldAnnotation 注解修饰 <br />
   *
   * @param clazz 集合泛型
   * @param <T>   泛型
   * @return 非主键元素别名集合
   */
  public static <T> List<Object> getAliasList(Class<T> clazz) {
    List<Object> aliasList = new ArrayList<>();
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
      field.setAccessible(true);
      RowKeyAnnotation rowKeyannotation = field.getAnnotation(RowKeyAnnotation.class);
      FieldAnnotation fieldAnnotation = field.getAnnotation(FieldAnnotation.class);
      if (rowKeyannotation == null && fieldAnnotation != null) {
        // 取出 属性别名保存到集合
        aliasList.add(fieldAnnotation.alias());
      }
    }
    return aliasList;
  }

  /**
   * 柱状图 折线图
   *
   * @param dataList 数据列表
   * @param clazz    集合泛型
   * @param <T>      泛型
   * @return 数据集合
   * @throws IllegalAccessException IllegalAccessException
   */
  public static <T> List<List<Object>> baseLine(List<T> dataList, Class<T> clazz) throws IllegalAccessException {
    List<List<Object>> rsList = new ArrayList<>();
    rsList.add(getRowKeyList(dataList, clazz));
    Field[] fields = clazz.getDeclaredFields();
    for (T data : dataList) {
      List<Object> list = new ArrayList<>();
      for (Field field : fields) {
        // 设置私有属性可以访问权限
        field.setAccessible(true);
        // 获取属性 RowKeyAnnotation 注解
        RowKeyAnnotation rowKeyannotation = field.getAnnotation(RowKeyAnnotation.class);
        // 获取属性 FieldAnnotation 注解
        FieldAnnotation fieldAnnotation = field.getAnnotation(FieldAnnotation.class);
        if (rowKeyannotation == null && fieldAnnotation != null) {
          list.add(field.get(data));
        }
      }
      rsList.add(list);
    }
    rsList.add(getAliasList(clazz));
    return rsList;
  }

  /**
   * 堆叠图
   *
   * @param dataList 数据列表
   * @param clazz    集合泛型
   * @param <T>      泛型
   * @return 数据集合
   * @throws IllegalAccessException IllegalAccessException
   */
  public static <T> List<List<Object>> pileUp(List<T> dataList, Class<T> clazz) throws IllegalAccessException {
    List<List<Object>> lists = baseLine(dataList, clazz);
    List<List<Object>> rList = transposeList(lists.subList(1, lists.size() - 1));
    rList.addFirst(lists.getFirst());
    rList.addLast(lists.getLast());
    return rList;
  }

  /**
   * 堆叠数据求和
   *
   * @param dataList 数据列表
   * @param clazz    集合泛型
   * @param <T>      泛型
   * @return 数据集合 计算
   * @throws IllegalAccessException IllegalAccessException
   */
  public static <T> List<List<Object>> pileUpTotal(List<T> dataList, Class<T> clazz) throws IllegalAccessException {
    List<List<Object>> rsList = baseLine(dataList, clazz);
    List<List<Object>> result = new ArrayList<>();
    result.addFirst(rsList.getFirst());
    List<Object> totalList = new ArrayList<>();
    for (int i = 1; i < rsList.size() - 1; i++) {
      rsList.get(i).stream().map(item -> Double.valueOf(item.toString())).reduce(Double::sum).ifPresent(totalList::add);
    }
    result.add(totalList);
    result.addLast(rsList.getLast());
    return result;
  }

  /**
   * 堆叠数据求和 转 地图数据
   *
   * @param dataList 数据列表
   * @param clazz    集合泛型
   * @param <T>      泛型
   * @return {name:"",value:""} 对象结合 计算
   * @throws IllegalAccessException IllegalAccessException
   */
  public static <T> List<Chart> pileUpTotalMap(List<T> dataList, Class<T> clazz) throws IllegalAccessException {
    List<List<Object>> lists = pileUpTotal(dataList, clazz);
    List<Chart> chartList = new ArrayList<>();
    List<Object> nameList = lists.getFirst();
    List<Object> valueList = lists.get(1);
    for (int i = 0; i < nameList.size(); i++) {
      chartList.add(new Chart(nameList.get(i).toString(), valueList.get(i)));
    }
    return chartList;
  }

  /**
   * 堆叠图 百分比计算
   *
   * @param dataList 数据列表
   * @param clazz    集合泛型
   * @param <T>      泛型
   * @return 数据集合 计算
   * @throws IllegalAccessException IllegalAccessException
   */
  public static <T> List<List<Object>> pileUpPercent(List<T> dataList, Class<T> clazz) throws IllegalAccessException {
    List<List<Object>> baseList = baseLine(dataList, clazz);
    List<List<Object>> result = new ArrayList<>();
    for (List<Object> list : baseList.subList(1, baseList.size() - 1)) {
      List<Double> doubleList = list.stream().map(item -> Double.valueOf(item.toString())).toList();
      Double total = doubleList.stream().reduce(Double::sum).orElse(0.0);
      result.add(doubleList.stream().map(item -> (Object) (item / total)).toList());
    }
    result = transposeList(result);
    result.addFirst(baseList.getFirst());
    result.addLast(baseList.getLast());
    return result;
  }

  /**
   * 饼图
   *
   * @param dataList 数据列表
   * @param <T>      泛型
   * @return 数据集合
   * @throws IllegalAccessException IllegalAccessException
   */
  public static <T> List<List<Object>> pie(List<T> dataList, Class<T> clazz) throws IllegalAccessException {
    List<List<Object>> rsList = new ArrayList<>();
    rsList.add(getRowKeyList(dataList, clazz));
    Field[] fields = clazz.getDeclaredFields();
    for (T data : dataList) {
      ArrayList<Object> list = new ArrayList<>();
      for (Field field : fields) {
        // 设置私有属性可以访问权限
        field.setAccessible(true);
        // 获取属性 RowKeyAnnotation 注解
        RowKeyAnnotation rowKeyannotation = field.getAnnotation(RowKeyAnnotation.class);
        // 获取属性 FieldAnnotation 注解
        FieldAnnotation fieldAnnotation = field.getAnnotation(FieldAnnotation.class);
        if (rowKeyannotation == null && fieldAnnotation != null) {
          list.add(new Chart(fieldAnnotation.alias(), field.get(data)));
        }
      }
      rsList.add(list);
    }
    rsList.add(getAliasList(clazz));
    return rsList;
  }

  /**
   * 计算每个子数组的元素
   *
   * @param inputArray 输入二维矩阵
   * @return 1轴向量的和的数组
   */
  public static double[][] normalizeArray(double[][] inputArray) {
    double[][] normalized = new double[inputArray.length][];
    for (int i = 0; i < inputArray.length; i++) {
      double sum = Arrays.stream(inputArray[i]).sum(); // 计算数组的总和
      normalized[i] = new double[inputArray[i].length];
      for (int j = 0; j < inputArray[i].length; j++) {
        normalized[i][j] = inputArray[i][j] / sum; // 每个元素除以总和
      }
    }
    return normalized;
  }

  /**
   * 行列转换
   *
   * @param inputArray 输入二维矩阵
   * @return 行列转换后的二维矩阵
   */
  public static Object[][] transposeArray(Object[][] inputArray) {
    int rows = inputArray.length;
    int cols = inputArray[0].length;
    Object[][] transposed = new Object[cols][rows];

    for (int i = 0; i < rows; i++) {
      for (int j = 0; j < cols; j++) {
        transposed[j][i] = inputArray[i][j]; // 行列互换
      }
    }
    return transposed;
  }

  /**
   * 计算每个子集合的元素
   *
   * @param inputList 输入二维矩阵
   * @return 1轴向量的和的集合
   */
  public static List<List<Double>> normalizeList(List<List<Double>> inputList) {
    List<List<Double>> normalizedList = new ArrayList<>();

    for (List<Double> sublist : inputList) {
      double sum = sublist.stream().mapToDouble(Double::doubleValue).sum(); // 计算子数组的总和

      List<Double> normalizedSublist = new ArrayList<>();
      for (Double value : sublist) {
        normalizedSublist.add(value / sum); // 每个元素除以总和
      }
      normalizedList.add(normalizedSublist); // 将归一化后的子数组添加到结果列表中
    }
    return normalizedList;
  }

  /**
   * 行列转换
   *
   * @param inputList 输入二维矩阵
   * @return 行列转换后的二维矩阵
   */
  public static List<List<Object>> transposeList(List<List<Object>> inputList) {
    int rows = inputList.size();
    int cols = inputList.getFirst().size();
    List<List<Object>> transposedList = new ArrayList<>();

    // 初始化转置列表
    for (int i = 0; i < cols; i++) {
      transposedList.add(new ArrayList<>(rows));
      for (int j = 0; j < rows; j++) {
        transposedList.get(i).add(0.0); // 填充初始值
      }
    }

    // 转换行列
    for (int i = 0; i < rows; i++) {
      for (int j = 0; j < cols; j++) {
        // 交换行列
        transposedList.get(j).set(i, inputList.get(i).get(j));
      }
    }
    return transposedList;
  }
}
